#pragma once
#include <iostream>
#include <string>
#include <functional>
#include "mytcp.hpp"
// #include"NetCal.hpp"
#include <jsoncpp/json/json.h>
std::string sep = "\r\n";
// 网络版计算器
class Request
{
public:
    Request(int x, int y, char oper)
        : _x(x), _y(y), _oper(oper)
    {
    }
    Request()
    {
    }
    // 序列化
    std::string Serialization()
    {
        // 序列化就是把_x,_y,_oper转换到json串里边
        Json::Value root;
        root["X"] = _x;
        root["Y"] = _y;
        root["OPER"] = _oper;
        Json::StyledWriter writer;
        std::string s = writer.write(root);
        return s;
    }
    // 反序列化
    bool Deserialization(std::string &get)
    {
        // 将json串提取
        Json::Value root;
        Json::Reader reader;
        bool ok = reader.parse(get, root);
        if (!ok)
        {
            // 提取失败
            return false;
        }
        _x = root["X"].asInt();
        _y = root["Y"].asInt();
        _oper = root["OPER"].asInt();
        return true;
    }
    int X()
    {
        return _x;
    }
    int Y()
    {
        return _y;
    }
    char OPER()
    {
        return _oper;
    }
    ~Request()
    {
    }

private:
    int _x;
    int _y;
    char _oper;
};
class Response
{
public:
    Response()
    {
    }
    Response(int result, int code)
        : _result(result), _code(code)
    {
    }
    // 序列化
    std::string Serialization()
    {
        Json::Value root;
        root["result"] = _result;
        root["code"] = _code;
        Json::StyledWriter writer;
        std::string s = writer.write(root);
        return s;
    }
    // 反序列化
    bool Deserialization(std::string &get)
    {
        Json::Value root;
        Json::Reader read;
        bool ok = read.parse(get, root);
        if (ok)
        {
            _result = root["result"].asInt();
            _code = root["code"].asInt();
            return true;
        }
        else
        {
            return false;
        }
    }
    // 打印结果
    void ShowResult()
    {
        std::cout << "result:" << _result << ' ' << "code:" << _code << std::endl;
    }
    ~Response()
    {
    }

private:
    int _result; // 结果
    int _code;   // 0表示成功,1,2,3,4表示不同情况的异常
};
using NetCal_t = std::function<Response(Request &q)>;
class Protocol
{
public:
    Protocol()
    {
    }
    Protocol(NetCal_t t)
        : _t(t)
    {
    }
    // 检测传进来的是否为一个完整的报文
    bool IsResponse(std::unique_ptr<Socket> &client, std::string &req_str, Response *p)
    {
        while (true)
        {
            int n = client->Recv(&req_str);
            //std::cout << "收到消息n1=" << n << std::endl;
            if (n > 0)
            {
                //std::cout << "收到消息n2=" << n << std::endl;
                std::string package;
                // 接收信息成功,判断是否为完整报文
                bool IsResp = Decode(req_str, &package);
                // 如果不是完整的报文,则继续Recv
                if (!IsResp)
                {
                    continue;
                }
                else
                {
                    // 获取到了完整报文,反序列化
                    p->Deserialization(package);
                    return true;
                }
            }
            else if (n == 0)
            {
                // 客户退出
                std::cout << "客户端退出" << std::endl;
                return false;
            }
            else
            {
                // 出现错误
                std::cout << "客户端接收信息出现错误" << std::endl;
                return false;
            }
        }
    }
    // 将给入得x,y,oper值按协议变化
    std::string BuildRequestString(int x, int y, char oper)
    {
        Request req(x, y, oper);
        // 序列化
        std::string req_str = req.Serialization();
        //std::cout << "序列化的内容" << std::endl;
        //std::cout << req_str << std::endl;
        // 加码
        std::string Encode_str = Encode(req_str);
        //std::cout << "协议后的内容" << std::endl;
        //std::cout << Encode_str << std::endl;
        int pos = Encode_str.find(sep);
        if (pos == std::string::npos)
        {
            std::cout << "客户端自己都没有找到任何一个sep" << std::endl;
        }
        return Encode_str;
    }
    // 加码函数
    std::string Encode(std::string &message) // messag就是一条json串的string形式
    {
        // 规定完整报文为:内容长度+\r\n+json串+\r\n
        int len = message.size();
        std::string ret = to_string(len) + sep + message + sep;
        return ret;
    }
    // 解码函数
    bool Decode(std::string &buffer, std::string *package)
    {
        // cout << "----------------要解析的报文---------------------" << endl;
        // cout << buffer << endl;
        // cout << buffer.size() << endl;
        // cout << "================================================" << endl;
        // std::cout << "buffer: " << buffer << std::endl;
        //  首先要找到sep,如果找不到就返回false
        size_t n = buffer.find(sep);
        if (n == std::string::npos)
        {
            // 没找到sep
            package = nullptr;
            // std::cout << "没有找到任何一个sep" << std::endl;
            return false;
        }
        // 找到了sep,所以sep之前的一定为报文长度
        std::string lenstr = buffer.substr(0, n);
        std::cout << "lenstr:" << lenstr << std::endl;
        int len = std::stoi(lenstr); // len为报文长度
        //std::cout << "len:" << len << std::endl;
        // 此刻我们就一定能推断出一条完整报文的长度
        int all = 2 * sep.size() + len + lenstr.size();
        int size = buffer.size();
        // std::cout << "size:" << size << std::endl;
        // std::cout << "all:" << all << std::endl;
        // 比较buffer和all的大小
        if (buffer.size() >= all) // 读到的报文长度大于等于一条完整报文的长度,说明一定有一条完整的报文存在其中
        {
            // 取报文
            *package = buffer.substr(n + sep.size(), len);
            // 因为可以同时存在一条以上的完整报文,所以要erase
            buffer.erase(0, all);
            // std::cout << "buffer: " << buffer << endl;
            // cout << "--------------------最后报文的长度----------------" << endl;
            // cout << buffer << endl;
            // cout << buffer.size() << endl;
            // cout << "cccccccccccccccccccccccccccccccccc" << endl;
            return true;
        }
        else // 不存在完整的一条报文,继续读
        {
            package = nullptr;
            std::cout << "报文长度不够" << std::endl;
            return false;
        }
    }
    // 服务函数
    void GetRequest(std::shared_ptr<Socket> &sock, Addr &client)
    {
        std::string inbuffer;
        while (true)
        {
            int n = sock->Recv(&inbuffer);
            // cout << "--------------读取数据----------------------" << endl;
            // cout << inbuffer << endl;
            // cout << inbuffer.size() << endl;
            // cout << "+++++++++++++++++++++++++++++++++++++++++++" << endl;
            std::cout << "从用户收到信息n=" << n << std::endl;
            if (n == 0) // 客户退出
            {
                LOG(LogLevel::INFO) << client.GetAddr() << "退出";
                break;
            }
            else if (n > 0)
            {
                // 读取消息成功,先进行解析
                std::string code;
                while (Decode(inbuffer, &code))
                {
                    // if (!ok) // 不是完整报文
                    // {
                    //     std::cout << "ok的值为假" << std::endl;
                    //     continue;
                    // }
                    //std::cout << "读到完整报文" << std::endl;
                    // 读到了完整报文,传给Request,进行反序列化
                    Request q;
                    bool get = q.Deserialization(code);
                    if (!get)
                    {
                        std::cout << "get的值为假" << std::endl;
                        // 反序列化失败
                        continue;
                    }
                    //std::cout << "Request反序列化成功" << std::endl;
                    // 开始进行处理
                    Response p = _t(q);
                    //std::cout << "结果处理成功" << std::endl;
                    // 拿到结果后进行序列化
                    std::string result = p.Serialization();
                    //std::cout << "将结果序列化成功" << std::endl;
                    // 加码
                    std::string send = Encode(result);
                    //std::cout << "将结果加码成功" << std::endl;
                    // 发送结果
                    sock->Send(send);
                    //std::cout << "结果成功发送给用户" << std::endl;
                }
            }
            else
            {
                LOG(LogLevel::ERROR) << client.GetAddr() << "接受信息出错";
                break;
            }
        }
    }
    ~Protocol()
    {
    }

private:
    NetCal_t _t;
    // Request _q;
    // Response _p;
};